# include <stdio.h>
# include <string.h>
# include <stdlib.h>

/*
    2022年4月25日
    pdudo
    使用C语言实现动态数组
*/

typedef struct {
        int *data; // 数组
        int cap; // 内存长度
        int len; // 使用长度
} Array, *PArray;

// 初始化动态数组
void initList(PArray LL,int n);
// 打印动态数组
void PrintArray(PArray pL);

// LL: PArray n: 初始化大小/动态扩容
void initList(PArray LL,int n) {
	// 判断如果传入的是空指针，则直接退出
        if (NULL == LL) return;

        printf("动态扩充:%d\n",n);
        // 初始化
        LL->cap = 0;
        LL->len = 0;

        // 动态分配 n 个空间
        LL->data = (int *)malloc(sizeof(int)*n);

	// 将n赋值给cap
        LL->cap = n;
}

// 追加函数
Array append(PArray LL,int v) {
        if (NULL == LL) return *LL; 

	// 当len < cap 的时候，此时容量还未被占满，所以可以直接追加
        if (LL->len+1 <= LL->cap) {
                // 赋值
		LL->data[LL->len] = v;
		// len+1
                LL->len++;
		// 返回动态数组
                return *LL;
        } else {
		// 这里指 len >= cap , 所以，需要重新开辟空间来存放数据
	        // 申请一个新的动态数组        
		Array newArry;
		
		// 初始化为老数组的2倍， 即: 若老数组容量为3 ，则新申请的数组容量为 3*2 ，即6
                initList(&newArry,LL->cap*2);
		
		// 将老数组 len 赋值给新数组
                newArry.len = LL->len;

                // 将老数组数据拷贝至新数组中
                //
                //memcpy(newArry.data,LL->data,(sizeof(int)*(LL->len)));
                int i;
                for (i=0;i<=LL->len;i++) {
                        newArry.data[i] = LL->data[i];
                }

                // 销毁老数组申请的内存
                free(LL->data);

                // 递归该函数，塞入数据
                newArry = append(&newArry,v);
        }  
}


int main() {
	// 申请动态数组LL
        Array LL;
	// 申请动态数组指针pL
        PArray pL;
	
	// 将LL的地址存储进pL中
        pL = &LL;

	// 初始化动态数组，cap为3
        initList(pL,3);

	// 我们插入10个数据，并且每一次插入都答应下 动态数组的起始地址，长度以及容量
        int i;
        for (i=1;i<=10;i++) {
                LL = append(&LL,i);
                //printf("i: %d\t main 函数 pL len: %d\n" ,i,pL->length);
		printf("slice起始地址: %p , slice长度: %d , slice容量: %d\n",pL->data,pL->len,pL->cap);
        }

	// 直接对动态数组赋值
	pL->data[0] = 1024;

	// 打印动态数组
        PrintArray(pL);

        return 0;
}

void PrintArray(PArray pL) {
        if (NULL == pL) return;

        int i;
        for (i=0;i<=pL->len-1;i++) {
                printf("id:%d\tdatas:%d\n",i,pL->data[i]);
        }
}
